//
//  ArcDataManager.swift
//  ZBDatePicker
//
//  Created by BO ZHOU on 2021/2/4.
//

import UIKit


/**
 * 负责所有日期数据获取单例类
 */
class ArcDataManager: NSObject {
    
    /** 单例 */
    static let shared: ArcDataManager = ArcDataManager()
    
    /** 当前时间 */
    var currentDate: Date {
        return Date()
    }
    
    /** 最小时间限制, 默认1970.1.1 */
    var minDate: Date = "1970-01-01".toDate(format: "yyyy-MM-dd") {
        didSet {
            clearCaches()
        }
    }
    
    /** 最大时间限制, 默认为当前时间 */
    var maxDate: Date! = Date() {
        didSet {
            clearCaches()
        }
    }
    
    /** 获取当前年份 */
    var currentYears: [Int] {
        return self.getYears()
    }
    
    /** 缓存: 当前展示的年份数组 */
    private var cachedYears: [Int] = []
    
    /** 缓存: 根据当前的时间限制, 对应年份下的月份数组字典, key为年份 */
    private var cachedMonthsDic: [Int: [Int]] = [:]
    
    /** 缓存: 日期数组 key为年份 * 100 + 月份 */
    private var cachedDaysDic: [Int: [Int]] = [:]
    
    private let fullMonthsInstance: [Int] = [1,2,3,4,5,6,7,8,9,10,11,12]
    
    // MARK: 公有方法
    
    /** 年份数组 */
    func getYears() -> [Int] {
        if cachedYears.count != 0 {
            return cachedYears
        }
        
        let minYear = minDate.year
        let maxYear = maxDate.year
        
        for i in minYear...maxYear {
            cachedYears.append(i)
        }
        return cachedYears
    }

    /** 月份数组 */
    func getMonthArr(withYear year: Int) -> [Int] {
        
        if let months = cachedMonthsDic[year] {
            return months
        }
        
        var monthArr: [Int] = []
        guard let maxDate = self.maxDate else {return []}
        
        // 设置了最大时间的情况下
        let maxYear = maxDate.year
        
        if year == maxYear {
            
            let maxMonth = maxDate.month
            let minMonth = 1
            
            for i in minMonth...maxMonth {
                monthArr.append(i)
            }
        } else if year < maxYear && year > minDate.year {
            monthArr = fullMonthsInstance
        } else if year == minDate.year {
            let minMonth = minDate.month
            let maxMonth = 12
            
            for i in minMonth...maxMonth {
                monthArr.append(i)
            }
        } else {
            monthArr = []
        }
        
        cachedMonthsDic[year] = monthArr
        
        return monthArr
    }
    
    
    /** 日期数组 */
    func getDayArr(withYear year: Int, month: Int) -> [Int] {
        
        let key = year * 100 + month
        if let days = cachedDaysDic[key] {
            return days
        }
        
        var dayArr: [Int] = []
        
        let maxDay = maxDate.day
        guard let maxDate = self.maxDate else {return []}
        
        let maxYear = maxDate.year
        let maxMonth = maxDate.month

        let totalDays = getDays(withYear: year, month: month)
        
        if year == maxYear && month == maxMonth {
            
            for i in 1...maxDay {
                dayArr.append(i)
            }
        } else if (year < maxYear && year > minDate.year) || (year == maxYear && month < maxMonth) || (year == minDate.year && month > minDate.month){
            for i in 1...totalDays {
                dayArr.append(i)
            }
        } else if year == minDate.year && month == minDate.month {
            
            let minDay = minDate.day
            for i in minDay...totalDays {
                dayArr.append(i)
            }
        } else {
            dayArr = []
        }
        
        cachedDaysDic[key] = dayArr
        return dayArr
    }
    
    
    // MARK: 私有方法
    
    /**
     * 根据(年,月)获取当月的天数
     */
    private func getDays(withYear year: Int, month: Int) -> Int {
        
        if year % 100 == 0 {
            if year % 400 == 0 {
                // 闰年
                return getDays(with: month, isLeapYear: true)
            } else {
                // 平年
                return getDays(with: month, isLeapYear: false)
            }
        } else if year % 4 == 0 {
            // 闰年
            return getDays(with: month, isLeapYear: true)
        } else {
            // 平年
            return getDays(with: month, isLeapYear: false)
        }
    }
    
    /**
     * 根据月份获取当月天数
     * - parameter month: 月份
     * - parameter isLeapYear: 是否为闰年
     */
    private func getDays(with month: Int, isLeapYear: Bool) -> Int {
        switch month {
        case 1, 3, 5, 7, 8, 10, 12:
            return 31
        case 2:
            if isLeapYear {
                return 29
            } else {
                return 28
            }
        case 4, 6, 9, 11:
            return 30
        default:
            return 30
        }
    }
    
    /**
     * 清除已缓存的数据
     */
    private func clearCaches() {
        self.cachedYears.removeAll()
        self.cachedDaysDic.removeAll()
        self.cachedMonthsDic.removeAll()
    }
}
